home *** CD-ROM | disk | FTP | other *** search
Oberon Text | 1993-10-25 | 9.2 KB | 219 lines | [.Ob./.Ob5] |
- Syntax10.Scn.Fnt
- MODULE PopupElems; (* Michael Franz, 25.10.93 -- "Hypertext without Surprises" *)
- IMPORT
- Oberon, Input, Display, Viewers, Files, Fonts, Printer, Texts, TextFrames, MenuViewers, TextPrinter;
- CONST
- edw=4; edh=2; mdw=3; mdh=1; CR=0DX; (* margins of element box and menu box *)
- TYPE
- PopupElem=POINTER TO PopupElemDesc;
- PopupElemDesc=RECORD (Texts.ElemDesc)
- name: ARRAY 32 OF CHAR;
- menu: Texts.Text; n, def, wid, lsp, dsc: INTEGER (* number of items, default, width, line space, descender *)
- END;
- EditFrame=POINTER TO EditFrameDesc;
- EditFrameDesc=RECORD (TextFrames.FrameDesc)
- elem: PopupElem
- END;
- buf: Texts.Buffer; (* copy buffer *)
- (* auxiliary *)
- PROCEDURE Min(x, y: INTEGER): INTEGER;
- BEGIN IF x<y THEN RETURN x ELSE RETURN y END
- END Min;
- PROCEDURE Max(x, y: INTEGER): INTEGER;
- BEGIN IF x>y THEN RETURN x ELSE RETURN y END
- END Max;
- (* change propagation *)
- PROCEDURE SetupElem(E: PopupElem; fnt: Fonts.Font);
- VAR i, wid, dx, x, y, w, h: INTEGER; p: LONGINT;
- BEGIN i:=0; wid:=2*edw+4;
- LOOP
- IF E.name[i]=0X THEN
- E.W:=LONG(wid+1)*TextFrames.Unit;
- E.H:=LONG(fnt.height-fnt.minY+2*edh+2)*TextFrames.Unit;
- RETURN
- ELSE Display.GetChar(fnt.raster, E.name[i], dx, x, y, w, h, p); INC(wid, dx); INC(i) END
- END
- END SetupElem;
- PROCEDURE SetupMenu(E: PopupElem);
- VAR R: Texts.Reader; ch: CHAR; wid, dx, x, y, w, h: INTEGER; p: LONGINT;
- BEGIN Texts.OpenReader(R, E.menu, 0); E.wid:=0; E.n:=1; E.lsp:=0; wid:=0;
- LOOP Texts.Read(R, ch);
- IF R.eot THEN E.wid:=Max(E.wid, wid); E.def:=Min(E.def, E.n-1); RETURN
- ELSIF ch=CR THEN E.wid:=Max(E.wid, wid); wid:=0; INC(E.n)
- ELSE E.lsp:=Max(E.lsp, R.fnt.height); E.dsc:=Min(E.dsc, R.fnt.minY);
- Display.GetChar(R.fnt.raster, ch, dx, x, y, w, h, p); INC(wid, dx)
- END
- END
- END SetupMenu;
- (* interactive editing of popup menus *)
- PROCEDURE* EditHandle(F: Display.Frame; VAR M: Display.FrameMsg);
- VAR F1: EditFrame;
- BEGIN
- WITH F:EditFrame DO TextFrames.Handle(F, M);
- IF ((M IS Oberon.InputMsg) & (M(Oberon.InputMsg).id=Oberon.consume))
- OR ((M IS TextFrames.UpdateMsg) & (M(TextFrames.UpdateMsg).text=F.text))
- THEN SetupMenu(F.elem)
- ELSIF M IS Oberon.CopyMsg THEN NEW(F1);
- TextFrames.Open(F1, F.text, F.org); F1.elem:=F.elem; M(Oberon.CopyMsg).F:=F1
- END
- END
- END EditHandle;
- PROCEDURE OpenEditor(E: PopupElem);
- VAR V: Viewers.Viewer; F: EditFrame; x, y: INTEGER;
- BEGIN Oberon.AllocateUserViewer(Oberon.Par.vwr.X, x, y); NEW(F); F.elem:=E;
- TextFrames.Open(F, E.menu, 0); F.handle:=EditHandle;
- V:=MenuViewers.New(TextFrames.NewMenu(E.name, "System.Close "), F, TextFrames.menuH, x, y)
- END OpenEditor;
- (* file input/output *)
- PROCEDURE Load(VAR R: Files.Rider; E: PopupElem);
- VAR ch: CHAR; i: INTEGER;
- BEGIN i:=0; REPEAT Files.Read(R, ch); E.name[i]:=ch; INC(i) UNTIL ch=0X;
- E.name[i-1]:="."; E.name[i]:="."; E.name[i+1]:="."; E.name[i+2]:=0X; SetupElem(E, Fonts.Default);
- Files.Read(R, ch); E.def:=ORD(ch); E.menu:=TextFrames.Text(""); Texts.Load(R, E.menu)
- END Load;
- PROCEDURE Store(VAR R: Files.Rider; E: PopupElem);
- VAR i: INTEGER;
- BEGIN i:=0; WHILE E.name[i] # 0X DO INC(i) END;
- Files.WriteBytes(R, E.name, i-3); Files.Write(R, 0X);
- Files.Write(R, CHR(E.def MOD 128)); Texts.Store(R, E.menu)
- END Store;
- (* graphics *)
- PROCEDURE Box(col, X, Y, W, H: INTEGER);
- BEGIN
- Display.ReplConst(col, X+1, Y+1, W-2, 1, Display.replace);
- Display.ReplConst(col, X+1, Y+H-2, W-2, 1, Display.replace);
- Display.ReplConst(col, X+1, Y+2, 1, H-4, Display.replace);
- Display.ReplConst(col, X+W-2, Y+2, 1, H-4, Display.replace);
- Display.ReplConst(col, X+4, Y, W-4, 1, Display.replace);
- Display.ReplConst(col, X+W-1, Y+1, 1, H-4, Display.replace);
- Display.ReplConst(Display.black, X+2, Y+2, W-4, H-4, Display.replace)
- END Box;
- PROCEDURE PrintElem(E: PopupElem; X, Y: INTEGER; fnt: Fonts.Font);
- VAR W, H: INTEGER;
- BEGIN W:=SHORT((E.W-1) DIV TextPrinter.Unit); H:=SHORT(E.H DIV TextPrinter.Unit);
- Printer.ReplConst(X, Y, W, 2);
- Printer.ReplConst(X, Y+H-2, W, 2);
- Printer.ReplConst(X, Y+2, 2, H-4);
- Printer.ReplConst(X+W-2, Y+2, 2, H-4);
- Printer.String(X+edw+2, Y+edh+2+fnt.minY, E.name, fnt.name)
- END PrintElem;
- PROCEDURE DrawElem(E: PopupElem; col, X, Y: INTEGER; fnt: Fonts.Font);
- VAR i, dx, x, y, w, h: INTEGER; p: LONGINT;
- BEGIN Box(col, X, Y, SHORT((E.W-1) DIV TextFrames.Unit), SHORT(E.H DIV TextFrames.Unit));
- INC(X, edw+2); INC(Y, edh+2-fnt.minY); i:=0;
- WHILE E.name[i] >= " " DO Display.GetChar(fnt.raster, E.name[i], dx, x, y, w, h, p);
- Display.CopyPattern(col, p, X+x, Y+y, Display.replace); INC(X, dx); INC(i)
- END
- END DrawElem;
- PROCEDURE DrawMenu(E: PopupElem; X, Y, W, H: INTEGER);
- VAR R: Texts.Reader; ch: CHAR; X0, dx, x, y, w, h: INTEGER; p: LONGINT;
- BEGIN Box(Display.white, X, Y, W, H);
- Texts.OpenReader(R, E.menu, 0); X0:=X+mdw+2; X:=X0; Y:=Y+H-E.lsp-E.dsc-mdh-2;
- LOOP Texts.Read(R, ch);
- IF R.eot THEN RETURN
- ELSIF ch=CR THEN Y:=Y-E.lsp; X:=X0
- ELSE Display.GetChar (R.fnt.raster, ch, dx, x, y, w, h, p);
- Display.CopyPattern(Display.white, p, X+x, Y+y, Display.replace); INC(X, dx)
- END
- END
- END DrawMenu;
- (* actions *)
- PROCEDURE Show(E: PopupElem; X, Y, W, H: INTEGER; VAR cmd: INTEGER);
- VAR mx, my, top, bot, left, right, newCmd: INTEGER; keys: SET;
- BEGIN left:=X+3; right:=X+W-3; bot:=Y+mdh+3; top:=Y+H-mdh-2;
- Oberon.RemoveMarks(X, Y, W, H); Oberon.FadeCursor(Oberon.Mouse);
- Display.CopyBlock(X, Y, W, H, X, -H, Display.replace); DrawMenu(E, X, Y, W, H);
- Display.ReplConst(Display.white, X+3, top-cmd*E.lsp-E.lsp, W-6, E.lsp, Display.invert);
- REPEAT Input.Mouse(keys, mx, my);
- Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, mx, my);
- IF keys*{0,2} # {} THEN Oberon.FadeCursor(Oberon.Mouse);
- Display.CopyBlock(X, -H, W, H, X, Y, Display.replace);
- IF 0 IN keys THEN OpenEditor(E) END;
- REPEAT Input.Mouse(keys, mx, my);
- Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, mx, my)
- UNTIL keys={};
- cmd:=-1; RETURN
- ELSIF (mx>=left) & (mx<=right) & (my>=bot) & (my<=top) THEN newCmd:=(top-my) DIV E.lsp;
- IF newCmd # cmd THEN
- IF cmd # -1 THEN
- Display.ReplConst(Display.white, X+3, top-cmd*E.lsp-E.lsp, W-6, E.lsp, Display.invert)
- END;
- Display.ReplConst(Display.white, X+3, top-newCmd*E.lsp-E.lsp, W-6, E.lsp, Display.invert);
- cmd:=newCmd
- END
- ELSIF cmd # -1 THEN
- Display.ReplConst(Display.white, X+3, top-cmd*E.lsp-E.lsp, W-6, E.lsp, Display.invert); cmd:=-1
- END
- UNTIL keys={};
- Oberon.FadeCursor(Oberon.Mouse); Display.CopyBlock(X, -H, W, H, X, Y, Display.replace);
- END Show;
- PROCEDURE Popup(E: PopupElem; X, Y: INTEGER; F: Display.Frame);
- VAR W, H, mx, my, j, cmd: INTEGER; r: Texts.Reader; ch: CHAR; keys: SET; i, res: INTEGER; cmdStr: ARRAY 32 OF CHAR;
- BEGIN Input.Mouse(keys, mx, my); W:=E.wid+2*mdw+4; H:=E.n*E.lsp+2*mdh+4;
- Y:=Max(my-H+E.lsp+E.def*E.lsp, 0); cmd:=E.def;
- IF X+W > Display.Width THEN X:=Display.Width-W END;
- IF Y+H > Display.Height THEN Y:=Display.Height-H END;
- Show(E, X, Y, W, H, cmd);
- IF cmd > -1 THEN E.def:=cmd; j:=0; Texts.OpenReader(r, E.menu, 0); Texts.Read(r, ch);
- WHILE j < cmd DO
- IF ch=CR THEN INC(j) END;
- Texts.Read(r, ch)
- END;
- i:=0;
- WHILE (ch>" ") & (i<31) DO cmdStr[i]:=ch; INC(i); Texts.Read(r, ch) END;
- cmdStr[i]:=0X;
- Oberon.Par.frame:=F; Oberon.Par.text:=E.menu; Oberon.Par.pos:=Texts.Pos(r)-1;
- Oberon.Call(cmdStr, Oberon.Par, FALSE, res)
- END
- END Popup;
- (* element *)
- PROCEDURE* Handle(E: Texts.Elem; VAR msg: Texts.ElemMsg);
- VAR e: PopupElem;
- BEGIN
- WITH E:PopupElem DO
- IF msg IS TextFrames.DisplayMsg THEN
- WITH msg:TextFrames.DisplayMsg DO
- IF msg.prepare THEN SetupElem(E, msg.fnt)
- ELSE DrawElem(E, msg.col, msg.X0, msg.Y0, msg.fnt) END
- END
- ELSIF msg IS TextPrinter.PrintMsg THEN
- WITH msg:TextPrinter.PrintMsg DO
- IF ~msg.prepare THEN PrintElem(E, msg.X0, msg.Y0, msg.fnt) END
- END
- ELSIF msg IS Texts.CopyMsg THEN
- WITH msg:Texts.CopyMsg DO
- NEW(e); Texts.CopyElem(E, e); e.name:=E.name; e.def:=E.def; e.wid:=E.wid; e.lsp:=E.lsp; e.dsc:=E.dsc; e.n:=E.n;
- e.menu:=TextFrames.Text(""); Texts.Save(E.menu, 0, E.menu.len, buf); Texts.Append(e.menu, buf); msg.e:=e
- END
- ELSIF msg IS Texts.IdentifyMsg THEN
- WITH msg:Texts.IdentifyMsg DO
- msg.mod:="PopupElems"; msg.proc:="Alloc"
- END
- ELSIF msg IS Texts.FileMsg THEN
- WITH msg:Texts.FileMsg DO
- IF msg.id=Texts.load THEN Load(msg.r, E); SetupMenu(E)
- ELSIF msg.id=Texts.store THEN Store(msg.r, E) END
- END
- ELSIF msg IS TextFrames.TrackMsg THEN
- WITH msg:TextFrames.TrackMsg DO
- IF msg.keys={1} THEN Popup(E, msg.X0, msg.Y0, msg.frame) END
- END
- END
- END
- END Handle;
- PROCEDURE Alloc*;
- VAR E: PopupElem;
- BEGIN NEW(E); E.handle:=Handle; Texts.new:=E
- END Alloc;
- PROCEDURE Insert*;
- VAR E: PopupElem; S: Texts.Scanner; i: INTEGER; msg: TextFrames.InsertElemMsg;
- BEGIN NEW(E); Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);
- IF S.class # Texts.String THEN S.s:="Popup" END;
- i:=0; REPEAT E.name[i]:=S.s[i]; INC(i) UNTIL S.s[i]=0X;
- E.name[i]:="."; E.name[i+1]:="."; E.name[i+2]:="."; E.name[i+3]:=0X; SetupElem(E, Fonts.Default);
- E.menu:=TextFrames.Text(""); SetupMenu(E); E.handle:=Handle;
- msg.e:=E; Oberon.FocusViewer.handle(Oberon.FocusViewer, msg)
- END Insert;
- BEGIN NEW(buf); Texts.OpenBuf(buf)
- END PopupElems.
-